{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "AAAc0ox9WpIj"
      },
      "source": [
        "<font color=\"red\">注</font>: 使用 tensorboard 可视化需要安装 tensorflow (TensorBoard依赖于tensorflow库，可以任意安装tensorflow的gpu/cpu版本)\n",
        "\n",
        "```shell\n",
        "pip install tensorflow-cpu\n",
        "```"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-01-18T02:58:38.837518Z",
          "start_time": "2025-01-18T02:58:30.898391Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "iDh3z67jWpIm",
        "outputId": "5b70b27f-ade1-4641-d952-bb5e4f069349"
      },
      "source": [
        "import matplotlib as mpl\n",
        "import matplotlib.pyplot as plt\n",
        "%matplotlib inline\n",
        "import numpy as np\n",
        "import sklearn\n",
        "import pandas as pd\n",
        "import os\n",
        "import sys\n",
        "import time\n",
        "from tqdm.auto import tqdm\n",
        "import torch\n",
        "import torch.nn as nn\n",
        "import torch.nn.functional as F\n",
        "\n",
        "print(sys.version_info)\n",
        "for module in mpl, np, pd, sklearn, torch:\n",
        "    print(module.__name__, module.__version__)\n",
        "\n",
        "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
        "print(device)\n",
        "\n",
        "seed = 42\n"
      ],
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "sys.version_info(major=3, minor=11, micro=11, releaselevel='final', serial=0)\n",
            "matplotlib 3.10.0\n",
            "numpy 1.26.4\n",
            "pandas 2.2.2\n",
            "sklearn 1.6.0\n",
            "torch 2.5.1+cu121\n",
            "cuda:0\n"
          ]
        }
      ],
      "execution_count": 1
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "NbGJU2I8WpIo"
      },
      "source": [
        "## 数据准备"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-01-18T03:00:30.781884Z",
          "start_time": "2025-01-18T03:00:25.548936Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "kSM-nMr3WpIo",
        "outputId": "88408410-f6a4-45a4-bf79-77cd95585588"
      },
      "source": [
        "from torchvision import datasets\n",
        "from torchvision.transforms import ToTensor\n",
        "from torch.utils.data import random_split\n",
        "\n",
        "# fashion_mnist图像分类数据集\n",
        "train_ds = datasets.FashionMNIST(\n",
        "    root=\"data\",\n",
        "    train=True,\n",
        "    download=True,\n",
        "    transform=ToTensor()\n",
        ")\n",
        "\n",
        "test_ds = datasets.FashionMNIST(\n",
        "    root=\"data\",\n",
        "    train=False,\n",
        "    download=True,\n",
        "    transform=ToTensor()\n",
        ")\n",
        "\n",
        "# torchvision 数据集里没有提供训练集和验证集的划分\n",
        "# 这里用 random_split 按照 11 : 1 的比例来划分数据集\n",
        "train_ds, val_ds = random_split(train_ds, [55000, 5000], torch.Generator().manual_seed(seed))"
      ],
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-images-idx3-ubyte.gz\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-images-idx3-ubyte.gz to data/FashionMNIST/raw/train-images-idx3-ubyte.gz\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "100%|██████████| 26.4M/26.4M [00:02<00:00, 12.8MB/s]\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Extracting data/FashionMNIST/raw/train-images-idx3-ubyte.gz to data/FashionMNIST/raw\n",
            "\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-labels-idx1-ubyte.gz\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/train-labels-idx1-ubyte.gz to data/FashionMNIST/raw/train-labels-idx1-ubyte.gz\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "100%|██████████| 29.5k/29.5k [00:00<00:00, 200kB/s]\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Extracting data/FashionMNIST/raw/train-labels-idx1-ubyte.gz to data/FashionMNIST/raw\n",
            "\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-images-idx3-ubyte.gz\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-images-idx3-ubyte.gz to data/FashionMNIST/raw/t10k-images-idx3-ubyte.gz\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "100%|██████████| 4.42M/4.42M [00:01<00:00, 3.73MB/s]\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Extracting data/FashionMNIST/raw/t10k-images-idx3-ubyte.gz to data/FashionMNIST/raw\n",
            "\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-labels-idx1-ubyte.gz\n",
            "Downloading http://fashion-mnist.s3-website.eu-central-1.amazonaws.com/t10k-labels-idx1-ubyte.gz to data/FashionMNIST/raw/t10k-labels-idx1-ubyte.gz\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "100%|██████████| 5.15k/5.15k [00:00<00:00, 26.4MB/s]"
          ]
        },
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Extracting data/FashionMNIST/raw/t10k-labels-idx1-ubyte.gz to data/FashionMNIST/raw\n",
            "\n"
          ]
        },
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "\n"
          ]
        }
      ],
      "execution_count": 2
    },
    {
      "cell_type": "code",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-01-18T03:00:37.780015Z",
          "start_time": "2025-01-18T03:00:37.777248Z"
        },
        "id": "BHO7CjXaWpIp"
      },
      "source": [
        "from torchvision.transforms import Normalize\n",
        "\n",
        "# 遍历train_ds得到每张图片，计算每个通道的均值和方差\n",
        "def cal_mean_std(ds):\n",
        "    mean = 0.\n",
        "    std = 0.\n",
        "    for img, _ in ds:\n",
        "        mean += img.mean(dim=(1, 2))\n",
        "        std += img.std(dim=(1, 2))\n",
        "    mean /= len(ds)\n",
        "    std /= len(ds)\n",
        "    return mean, std\n",
        "\n",
        "\n",
        "# print(cal_mean_std(train_ds))\n",
        "# 0.2860， 0.3205\n",
        "transforms = nn.Sequential(\n",
        "    Normalize([0.2856], [0.3202])\n",
        ") # 对每个通道进行标准化"
      ],
      "outputs": [],
      "execution_count": 3
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {
        "jupyter": {
          "outputs_hidden": false
        },
        "ExecuteTime": {
          "end_time": "2024-07-22T02:00:57.936968200Z",
          "start_time": "2024-07-22T02:00:57.892838900Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "tGcrAiK-WpIp",
        "outputId": "1e918371-fbd8-4bbe-cef5-eb646b15d020"
      },
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(torch.Size([1, 28, 28]), 9)"
            ]
          },
          "metadata": {},
          "execution_count": 4
        }
      ],
      "source": [
        "img, label = train_ds[0]\n",
        "img.shape, label"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-01-18T03:00:57.771910Z",
          "start_time": "2025-01-18T03:00:57.769338Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "wc0cQPtWWpIq",
        "outputId": "3c2e51f3-27cb-49d8-ee29-9cd29789cac6"
      },
      "source": [
        "from torch.utils.data.dataloader import DataLoader\n",
        "\n",
        "batch_size = 32\n",
        "# 从数据集到dataloader\n",
        "train_loader = DataLoader(train_ds, batch_size=batch_size, shuffle=True, num_workers=4)\n",
        "val_loader = DataLoader(val_ds, batch_size=batch_size, shuffle=False, num_workers=4)\n",
        "test_loader = DataLoader(test_ds, batch_size=batch_size, shuffle=False, num_workers=4)"
      ],
      "outputs": [
        {
          "output_type": "stream",
          "name": "stderr",
          "text": [
            "/usr/local/lib/python3.11/dist-packages/torch/utils/data/dataloader.py:617: UserWarning: This DataLoader will create 4 worker processes in total. Our suggested max number of worker in current system is 2, which is smaller than what this DataLoader is going to create. Please be aware that excessive worker creation might get DataLoader running slow or even freeze, lower the worker number to avoid potential slowness/freeze if necessary.\n",
            "  warnings.warn(\n"
          ]
        }
      ],
      "execution_count": 5
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "gCPfNysVWpIq"
      },
      "source": [
        "## 定义模型"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "ExecuteTime": {
          "end_time": "2024-04-26T03:02:10.528861Z",
          "start_time": "2024-04-26T03:02:10.513869500Z"
        },
        "jupyter": {
          "outputs_hidden": false
        },
        "id": "d3x4nnb0WpIq",
        "outputId": "3d8fd95b-fbf9-4ab6-d50d-3db34b27816b"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "1152"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "128*9"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-01-18T03:15:54.808180Z",
          "start_time": "2025-01-18T03:15:54.796350Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "4ZyftkANWpIr",
        "outputId": "232a13b7-a7fd-412e-a103-1e47afa5db0c"
      },
      "source": [
        "class CNN(nn.Module):\n",
        "    def __init__(self, activation=\"relu\"):\n",
        "        super(CNN, self).__init__()\n",
        "        self.activation = F.relu if activation == \"relu\" else F.selu\n",
        "        #输入通道数，图片是灰度图，所以是1，图片是彩色图，就是3，输出通道数，就是卷积核的个数（32,1,28,28）\n",
        "        #输入x(32,1,28,28) 输出x(32,32,28,28)\n",
        "        self.conv1 = nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, padding=1)\n",
        "        #输入x(32,32,28,28) 输出x(32,32,28,28)\n",
        "\n",
        "        self.conv2 = nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, padding=1)\n",
        "        self.pool = nn.MaxPool2d(2, 2) #池化核大小为2（2*2），步长为2\n",
        "\n",
        "        self.conv3 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1)\n",
        "        self.conv4 = nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, padding=1)\n",
        "        self.conv5 = nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, padding=1)\n",
        "        self.conv6 = nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, padding=1)\n",
        "        self.flatten = nn.Flatten()\n",
        "        # input shape is (28, 28, 1) so the fc1 layer in_features is 128 * 3 * 3\n",
        "        self.fc1 = nn.Linear(128 * 3 * 3, 128)\n",
        "        self.fc2 = nn.Linear(128, 10) #输出尺寸（32,10）\n",
        "\n",
        "        self.init_weights()\n",
        "\n",
        "    def init_weights(self):\n",
        "        \"\"\"使用 xavier 均匀分布来初始化全连接层、卷积层的权重 W\"\"\"\n",
        "        for m in self.modules():\n",
        "            if isinstance(m, (nn.Linear, nn.Conv2d)):\n",
        "                nn.init.xavier_uniform_(m.weight)\n",
        "                nn.init.zeros_(m.bias)\n",
        "\n",
        "    def forward(self, x):\n",
        "        act = self.activation\n",
        "        x = self.pool(act(self.conv2(act(self.conv1(x))))) # 1 * 28 * 28 -> 32 * 14 * 14\n",
        "        print(x.shape)\n",
        "        x = self.pool(act(self.conv4(act(self.conv3(x))))) # 32 * 14 * 14 -> 64 * 7 * 7\n",
        "        print(x.shape)\n",
        "        x = self.pool(act(self.conv6(act(self.conv5(x))))) # 64 * 7 * 7 -> 128 * 3 * 3\n",
        "        print(x.shape)\n",
        "        x = self.flatten(x) # 128 * 3 * 3 ->1152\n",
        "        x = act(self.fc1(x)) # 1152 -> 128\n",
        "        x = self.fc2(x) # 128 -> 10\n",
        "        return x\n",
        "\n",
        "\n",
        "for idx, (key, value) in enumerate(CNN().named_parameters()):\n",
        "    print(f\"{key}\\tparamerters num: {np.prod(value.shape)}\") # 打印模型的参数信息\n"
      ],
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "conv1.weight\tparamerters num: 288\n",
            "conv1.bias\tparamerters num: 32\n",
            "conv2.weight\tparamerters num: 9216\n",
            "conv2.bias\tparamerters num: 32\n",
            "conv3.weight\tparamerters num: 18432\n",
            "conv3.bias\tparamerters num: 64\n",
            "conv4.weight\tparamerters num: 36864\n",
            "conv4.bias\tparamerters num: 64\n",
            "conv5.weight\tparamerters num: 73728\n",
            "conv5.bias\tparamerters num: 128\n",
            "conv6.weight\tparamerters num: 147456\n",
            "conv6.bias\tparamerters num: 128\n",
            "fc1.weight\tparamerters num: 147456\n",
            "fc1.bias\tparamerters num: 128\n",
            "fc2.weight\tparamerters num: 1280\n",
            "fc2.bias\tparamerters num: 10\n"
          ]
        }
      ],
      "execution_count": 13
    },
    {
      "metadata": {
        "ExecuteTime": {
          "end_time": "2025-01-18T03:17:11.857946Z",
          "start_time": "2025-01-18T03:17:11.854987Z"
        },
        "id": "zWqgA4s2WpIs",
        "outputId": "a8d2f12c-3ce2-45b9-b5fc-efd11a3c304f"
      },
      "cell_type": "code",
      "source": [
        "3*3*32    *32"
      ],
      "outputs": [
        {
          "data": {
            "text/plain": [
              "9216"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "execution_count": null
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "outputs": [],
      "source": [
        "#练习不同尺寸的卷积核，padding，stride的效果\n",
        "class CNN1(nn.Module):\n",
        "    def __init__(self, activation=\"relu\"):\n",
        "        super(CNN, self).__init__()\n",
        "        self.activation = F.relu if activation == \"relu\" else F.selu\n",
        "        #输入通道数，图片是灰度图，所以是1，图片是彩色图，就是3，输出通道数，就是卷积核的个数（32,1,28,28）\n",
        "        self.conv1 = nn.Conv2d(in_channels=1, out_channels=32, kernel_size=5,padding=2,stride=2)\n",
        "        #输入x(32,32,28,28) 输出x(32,32,28,28)\n",
        "        self.conv2 = nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, padding=1)\n",
        "        self.pool = nn.MaxPool2d(2, 2) #池化核大小为2（2*2），步长为2\n",
        "        self.conv3 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1)\n",
        "        self.conv4 = nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, padding=1)\n",
        "        self.conv5 = nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, padding=1)\n",
        "        self.conv6 = nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, padding=1)\n",
        "        self.flatten = nn.Flatten()\n",
        "        # input shape is (28, 28, 1) so the fc1 layer in_features is 128 * 3 * 3\n",
        "        self.fc1 = nn.Linear(128 * 3 * 3, 128)\n",
        "        self.fc2 = nn.Linear(128, 10) #输出尺寸（32,10）\n",
        "\n",
        "        self.init_weights()\n",
        "\n",
        "    def init_weights(self):\n",
        "        \"\"\"使用 xavier 均匀分布来初始化全连接层、卷积层的权重 W\"\"\"\n",
        "        for m in self.modules():\n",
        "            if isinstance(m, (nn.Linear, nn.Conv2d)):\n",
        "                nn.init.xavier_uniform_(m.weight)\n",
        "                nn.init.zeros_(m.bias)\n",
        "\n",
        "    def forward(self, x):\n",
        "        act = self.activation\n",
        "        x=act(self.conv1(x)) # 1 * 28 * 28 -> 32 * 28 * 28\n",
        "        print(x.shape)\n",
        "        # x=act(self.conv2(x)) # 32 * 28 * 28 -> 32 * 28 * 28\n",
        "        # print(x.shape)\n",
        "        # x = self.pool(x) # 32 * 28 * 28 -> 32 * 14 * 14\n",
        "        # print(x.shape)\n",
        "        # x=act(self.conv3(x)) # 32 * 14 * 14 -> 64 * 14 * 14\n",
        "        # print(x.shape)\n",
        "        # x=act(self.conv4(x)) # 64 * 14 * 14 -> 64 * 14 * 14\n",
        "        # print(x.shape)\n",
        "        # x = self.pool(x) # 32 * 14 * 14 -> 64 * 7 * 7\n",
        "        # print(x.shape)\n",
        "        # x=act(self.conv5(x)) # 64 * 7 * 7 -> 128 * 7 * 7\n",
        "        # print(x.shape)\n",
        "        # x=act(self.conv6(x)) # 128 * 7 * 7 -> 128 * 7 * 7\n",
        "        # print(x.shape)\n",
        "        # x = self.pool(x) # 128 * 7 * 7 -> 128 * 3 * 3\n",
        "        # print(x.shape)\n",
        "        # x = self.flatten(x) # 128 * 3 * 3 ->1152\n",
        "        # x = act(self.fc1(x)) # 1152 -> 128\n",
        "        # x = self.fc2(x) # 128 -> 10\n",
        "        return x\n"
      ],
      "metadata": {
        "ExecuteTime": {
          "end_time": "2024-07-23T02:00:42.753973800Z",
          "start_time": "2024-07-23T02:00:42.742979500Z"
        },
        "id": "PS7XcnNUWpIs"
      }
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "torch.Size([1, 32, 14, 14])\n",
            "torch.Size([1, 64, 7, 7])\n",
            "torch.Size([1, 128, 3, 3])\n"
          ]
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "tensor([[-0.1335, -0.0232,  0.0271,  0.0725, -0.0584, -0.0092,  0.1143,  0.0762,\n",
              "         -0.0267, -0.0190]], grad_fn=<AddmmBackward0>)"
            ]
          },
          "metadata": {},
          "execution_count": 9
        }
      ],
      "source": [
        "activation = \"relu\"\n",
        "model = CNN(activation)\n",
        "# model.to(device)\n",
        "img = torch.randn(1, 1, 28, 28)\n",
        "model(img)"
      ],
      "metadata": {
        "ExecuteTime": {
          "end_time": "2024-07-23T02:01:15.751808600Z",
          "start_time": "2024-07-23T02:01:15.718775900Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "qrR5sYxpWpIt",
        "outputId": "e19db0c9-c874-4e50-d1cd-057b1b656c82"
      }
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "conv1.weight\tparamerters num: 288\n",
            "conv1.bias\tparamerters num: 32\n",
            "conv2.weight\tparamerters num: 9216\n",
            "conv2.bias\tparamerters num: 32\n",
            "conv3.weight\tparamerters num: 18432\n",
            "conv3.bias\tparamerters num: 64\n",
            "conv4.weight\tparamerters num: 36864\n",
            "conv4.bias\tparamerters num: 64\n",
            "conv5.weight\tparamerters num: 73728\n",
            "conv5.bias\tparamerters num: 128\n",
            "conv6.weight\tparamerters num: 147456\n",
            "conv6.bias\tparamerters num: 128\n",
            "fc1.weight\tparamerters num: 147456\n",
            "fc1.bias\tparamerters num: 128\n",
            "fc2.weight\tparamerters num: 1280\n",
            "fc2.bias\tparamerters num: 10\n"
          ]
        }
      ],
      "source": [
        "\n",
        "class CNN(nn.Module):\n",
        "    def __init__(self, activation=\"relu\"):\n",
        "        super(CNN, self).__init__()\n",
        "        self.activation = F.relu if activation == \"relu\" else F.selu\n",
        "        #输入通道数，图片是灰度图，所以是1，图片是彩色图，就是3，输出通道数，就是卷积核的个数（32,1,28,28）\n",
        "        self.conv1 = nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, padding=1)\n",
        "        #输入x(32,32,28,28) 输出x(32,32,28,28)\n",
        "        self.conv2 = nn.Conv2d(in_channels=32, out_channels=32, kernel_size=3, padding=1)\n",
        "        self.pool = nn.MaxPool2d(2, 2) #池化核大小为2（2*2），步长为2\n",
        "        self.conv3 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, padding=1)\n",
        "        self.conv4 = nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, padding=1)\n",
        "        self.conv5 = nn.Conv2d(in_channels=64, out_channels=128, kernel_size=3, padding=1)\n",
        "        self.conv6 = nn.Conv2d(in_channels=128, out_channels=128, kernel_size=3, padding=1)\n",
        "        self.flatten = nn.Flatten()\n",
        "        # input shape is (28, 28, 1) so the fc1 layer in_features is 128 * 3 * 3\n",
        "        self.fc1 = nn.Linear(128 * 3 * 3, 128)\n",
        "        self.fc2 = nn.Linear(128, 10) #输出尺寸（32,10）\n",
        "\n",
        "        self.init_weights()\n",
        "\n",
        "    def init_weights(self):\n",
        "        \"\"\"使用 xavier 均匀分布来初始化全连接层、卷积层的权重 W\"\"\"\n",
        "        for m in self.modules():\n",
        "            if isinstance(m, (nn.Linear, nn.Conv2d)):\n",
        "                nn.init.xavier_uniform_(m.weight)\n",
        "                nn.init.zeros_(m.bias)\n",
        "\n",
        "    def forward(self, x):\n",
        "        act = self.activation\n",
        "        x=act(self.conv1(x)) # 1 * 28 * 28 -> 32 * 28 * 28\n",
        "        print(x.shape)\n",
        "        x=act(self.conv2(x)) # 32 * 28 * 28 -> 32 * 28 * 28\n",
        "        print(x.shape)\n",
        "        x = self.pool(x) # 32 * 28 * 28 -> 32 * 14 * 14\n",
        "        print(x.shape)\n",
        "        x=act(self.conv3(x)) # 32 * 14 * 14 -> 64 * 14 * 14\n",
        "        print(x.shape)\n",
        "        x=act(self.conv4(x)) # 64 * 14 * 14 -> 64 * 14 * 14\n",
        "        print(x.shape)\n",
        "        x = self.pool(x) # 32 * 14 * 14 -> 64 * 7 * 7\n",
        "        print(x.shape)\n",
        "        x=act(self.conv5(x)) # 64 * 7 * 7 -> 128 * 7 * 7\n",
        "        print(x.shape)\n",
        "        x=act(self.conv6(x)) # 128 * 7 * 7 -> 128 * 7 * 7\n",
        "        print(x.shape)\n",
        "        x = self.pool(x) # 128 * 7 * 7 -> 128 * 3 * 3\n",
        "        print(x.shape)\n",
        "        x = self.flatten(x) # 128 * 3 * 3 ->1152\n",
        "        x = act(self.fc1(x)) # 1152 -> 128\n",
        "        x = self.fc2(x) # 128 -> 10\n",
        "        return x\n",
        "\n",
        "\n",
        "for idx, (key, value) in enumerate(CNN().named_parameters()):\n",
        "    print(f\"{key}\\tparamerters num: {np.prod(value.shape)}\") # 打印模型的参数信息\n"
      ],
      "metadata": {
        "ExecuteTime": {
          "end_time": "2024-07-23T03:04:53.570608600Z",
          "start_time": "2024-07-23T03:04:53.551722300Z"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "BaB_WsjRWpIt",
        "outputId": "d9ae98dd-34f2-47a8-be67-bb2e80d671cb"
      }
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.12.3"
    },
    "colab": {
      "provenance": [],
      "gpuType": "T4"
    },
    "accelerator": "GPU"
  },
  "nbformat": 4,
  "nbformat_minor": 0
}